#include "GSMv3.h"


#define PIN_GSM_PWR   PIN_C5                                                        //power ON pin
#define LED1		  PIN_A5                                                        //need to be set
#define LED2		  PIN_A4
#define LED3		  PIN_C4														//LED 3 is in interface board
#define LED4		  PIN_C5														//For testing only
#define UP_BTN		  PIN_B5
#define DW_BTN		  PIN_B6
#define RS_BTN		  PIN_B4
#define NUM_QUE {4,6,8,14,16,18,24,26,28,34,36,38,44,46,48,54,56,58,0}	  			//***make sure the last number is zero

#define DEBUG  ////**** comment this line when compiling for a release

//////////////////// Funtion Prototypes /////////////////////////////////////
void gsm_init(short state);         //power on the gsm module
void gsm_reg();
void sendmsg( char msg[], char num[]);
char* get_string(char dest[] , int len);
void check_sms();
void delete_sms(char sms_index_st[]);
void delay_with_pin(int time);
void inc_bcd();
void dec_bcd();
char eeprom_valid_read(char loc);
void eeprom_valid_write(char loc, char val);
//char init_eeprom();															//returns the valid eeprom base address for this session
char get_resv_num();
////////////////////////////////////////////////////////////////////////////

////////////////// Global Variables ////////////////////////////////////////
short reg = FALSE;                                                          // properly registered in operator network
short valid_sms = FALSE;													//filters out service SMSs which doesn't have a sender number
char home_num [13]="+94713017248";
char sms_index_st [2] = "";													//index number of the sms currently handled, required for deleting that sms, after reply is sent
short new_sms = FALSE;														// TRUE if there are any new SMSs as indicated by the response to CMGL
char reply_num [12]="";
char sms_count = 0;															//number of SMS replied to, for record keeping
char p_num = 0b01000101;	//45															//Current Patient Number
char p_num_s [3]="00";
char res_num_s [3] = "00";
char tcount = 10;															//required in RX ISR
char sms_count_string [3]= "00";
char cat_msg [50] = "";
char sms_msg [4]  = "";
char num_msg [4]   = "num";
char res_msg [4]   = "res";
int num_index = 0;

const char num_array[] = NUM_QUE ;
const char nw_srv_msg [14] = "Now Serving :";
const char num_resv_msg [18] = "Number Reserved :";
const char hlp_msg [] = "Please send NUM or RES"; 
const char que_end_msg [] = "Sorry, Numbers finished";

////////////////////////////////////////////////////////////////////////////

#int_rda
void serial_isr() {
	
    char rx_st1 [40];
	char i=8;

  	 
	get_string(rx_st1,40);

     if( (rx_st1[4] == 'L')){                                              									 // +CMGL
  		  output_bit(LED2,1);      
		  new_sms = TRUE;	
	  
		  sms_index_st[0] = rx_st1[7];
		  sms_index_st[1] = '0';

		  if(isdigit(rx_st1[8]))	{																		//if the SMS index is >9, needs special processing.. 
				sms_index_st[1] = rx_st1[7];																//..to record both digits of the index number
				sms_index_st[0] = rx_st1[8];
		 }

		  valid_sms = FALSE;
  		  while (TRUE)   {
	      	i++;
	      	if(rx_st1[i] == 43) { valid_sms = TRUE; break;}                                                //find the "+"
			if(i > 35) break;																			   // no + found, SMS not valid. proceed to delete 
	      	}

	      reply_num[0] = 43;
	      reply_num[1] = rx_st1[i+1];
	      reply_num[2] = rx_st1[i+2];
	      reply_num[3] = rx_st1[i+3];
	      reply_num[4] = rx_st1[i+4];
	      reply_num[5] = rx_st1[i+5];
	      reply_num[6] = rx_st1[i+6];
	      reply_num[7] = rx_st1[i+7];
	      reply_num[8] = rx_st1[i+8];
	      reply_num[9] = rx_st1[i+9];
	      reply_num[10] = rx_st1[i+10];
	      reply_num[11] = rx_st1[i+11];
		  get_string(sms_msg,3);
		  sms_msg[3] = 0;
      }   

 	 else if (rx_st1[3] == 'E' && rx_st1[9] == '1' ) {                           // +CREG: 0,1
  		 reg = TRUE;
		
	}
	tcount = 2;																	//refresing tcount to see if more lines are to be received

}


void main()	{
   
char address = 0;
char new_address = 0;
char resv_num = 0;
short RST=0;
char RST_delay= 10; //100mSec*100
char swtimer1=0;
char swtimer2=0;

#ifndef DEBUG
	delay_ms(1000);
#endif
	
	output_bit(LED3,1);

//to start with address should be 4 and value should be 0, first 4 eeprom locations should be set to number 4 at the very first start.
//and eeprom(4), (5),(6) should be set to zero

   address = eeprom_valid_read(0);
   if (address == 0) address = eeprom_valid_read(1); 			//something in locations 0,1,2 is corrupted, try again with locations 1,2,3 
   new_address = address;
   
   while(swtimer1<50){
	if(!RST)
		if(input(RS_BTN)){
			//display("RS");
			RST=1;
			swtimer2=0;
			}
	if(RST)
		if(input(!RS_BTN)){
			//display("NA");
			RST=0;
			}
		if(swtimer2>RST_delay){
			//display("ok");
			RST=0;
			output_bit(LED4,1);
			new_address = address + 3;
			if(new_address<3) new_address = 4;							//skip the first 4 locations in which the value of the address is stored
			eeprom_valid_write(0,new_address);
			write_eeprom(3,new_address);               					//just write to the loc 3, Why this?
			}
	delay_ms(100);
	swtimer1++;
	swtimer2++;
	}
	

   sms_count = eeprom_valid_read(address);
   itoa(sms_count, 10, sms_count_string);
   sms_count = 0;
   eeprom_valid_write(new_address, sms_count);
   

#ifndef DEBUG
	delay_ms(1000);
	setup_uart(0);
	gsm_init(1);
	delay_ms(1000);
#endif
	
	clear_interrupt(int_rda);
	enable_interrupts(int_rda);
	enable_interrupts(global);

#ifndef DEBUG
	delay_ms(1000);
	setup_uart(1);
	output_bit(LED1,1);
	delay_ms(1000);
	gsm_reg();
	output_bit(LED1,0);
	if(!reg) while(true);                                                       //if not registered loop with PIN_Error high

	itoa(sms_count, 10, sms_count_string);											//convert sms_count to a string
    sendmsg(sms_count_string , home_num);                                           //sending status message
#endif	


#ifndef DEBUG
    delay_ms(3000);
#endif

 while(TRUE)  {
	tcount = 2;
	output_bit(LED1,0);output_bit(LED2,0);
	check_sms();
	
	while(tcount>0)	{																//allow time after each received line to see if any more data is onthe way
		delay_with_pin(10);															//tcount is refreshed each time rx ISR is called
		tcount--;
	}

	delay_with_pin(10); 															//allowing time for the GSM module to respond with all received text messages
	output_bit(LED1,1);

	if(new_sms)		  {
         if(valid_sms && (reply_num[4] == '1')) { 
			 strlwr(sms_msg);
  		 	 if((strncmp((sms_msg),num_msg,3)== 0) )	{
				 strcpy(cat_msg,nw_srv_msg);
				 strcat(cat_msg, p_num_s);						//current number message
			 	}
			 else if((strncmp((sms_msg),res_msg,3)== 0) )	{
				 resv_num = get_resv_num();
				 if (resv_num != 0) 	{
				 	strcpy(cat_msg,num_resv_msg);
				 	itoa(resv_num,10,res_num_s);
				 	strcat(cat_msg, res_num_s);					// reserved number message
				    }
				 else strcpy(cat_msg,que_end_msg);				//all numbers reserved,
				}
			 else strcpy(cat_msg,hlp_msg);						// help message
			
			 sms_count++;  
			 eeprom_valid_write(new_address, sms_count);							
			
			 sendmsg(cat_msg, reply_num);

#ifndef DEBUG
			 delay_with_pin(20);
#else
			delay_with_pin(2);
#endif
		 }

         delete_sms(sms_index_st);
		 output_bit(LED2,1);
		 new_sms = FALSE; //sms_index = 0;
       }

#ifndef DEBUG	
	delay_with_pin(20);
#else
	delay_with_pin(2);
#endif	
	}
}

                                                     
void gsm_init(short state)   {

 if (state)   {                                                                 //switch on
    output_bit(PIN_GSM_PWR, 0);
    delay_ms(1000);
    output_bit(PIN_GSM_PWR, 1);
    delay_ms(2000);
    output_bit(PIN_GSM_PWR, 0);//

    delay_ms(20000);                                                            //wait till network registration

  }
}


void gsm_reg()   {

char reg_chk_cmd[9] = "at+creg?";
char attempts = 0;


while(!reg && attempts++ < 5)   {
        puts(reg_chk_cmd);
		delay_ms(3000);
      }

}


char* get_string(char dest[] , int len) {
char i,c;
i=0;

   while(TRUE) {
      c=getc();

      if(i<len) dest[i]= c;
      if (c==10) break;
      i++;
   }
   return dest;
}

void sendmsg(char msg[],char num[])   {

   disable_interrupts(global);                                                  //when sending do not bother about other interrupts
		
//////////////////////
    putc('a');    putc('t');    putc('+');    putc('c');    putc('m');    putc('g');    putc('s');
    putc('=');
    putc('"');
    putc(num[0]);    putc(num[1]);    putc(num[2]);    putc(num[3]);    putc(num[4]);    putc(num[5]);
    putc(num[6]);    putc(num[7]);    putc(num[8]);    putc(num[9]);    putc(num[10]);    putc(num[11]);
    putc('"');
    putc(13);
////////////////////////

   while(!kbhit());                                                             //wait for input
   while(getc() != 32);                                                         //if input char is 'space' then proceed to sending msg txt
   puts(msg);
                                       
   if(strncmp(home_num,num,12)== 0 )	{										//if home num, then send sms_count as well
		itoa(sms_count, 10, sms_count_string);
		putc(10); putc(sms_count_string[0]); putc(sms_count_string[1]); 
	}

   putc(26);																	//ctrl+z
   enable_interrupts(global);
   
  }

void check_sms()   {

    putc('a');    putc('t');    putc('+');    putc('c');    putc('m');    putc('g');    putc('l');
    putc('=');    putc('"');
    putc('a');    putc('l');    putc('l');
    putc('"');
    putc(13);
}

void delete_sms(char sms_index_st[])   {

    putc('a');    putc('t');    putc('+');    putc('c');    putc('m');    putc('g');    putc('d');
    putc('=');    putc(sms_index_st[1]);  putc(sms_index_st[0]);
    putc(13);
	
}

void delay_with_pin(int time)	{

	int i =0;
	for(i=0; i<=time; i++)	{
	if(input(UP_BTN)) { while(input(UP_BTN)); inc_bcd();}
    if(input(DW_BTN)) { while(input(DW_BTN)); dec_bcd();}
	if(input(RS_BTN)) { while(input(RS_BTN)); p_num = 0;}


	output_bit(PIN_B0,bit_test(p_num,4));
	output_bit(PIN_B1,bit_test(p_num,5));
	output_bit(PIN_B2,bit_test(p_num,6));
	output_bit(PIN_B3,bit_test(p_num,7));

	output_bit(PIN_A0,bit_test(p_num,0));
	output_bit(PIN_A1,bit_test(p_num,1));
	output_bit(PIN_A2,bit_test(p_num,2));
	output_bit(PIN_A3,bit_test(p_num,3));


	p_num_s[1] = (p_num & 0b00001111)+48;
	p_num_s[0] = ((p_num & 0b11110000)/16)+48;

#ifndef DEBUG	
	delay_ms(100);
#endif
										
#ifdef DEBUG
	delay_ms(1);
#endif

	} 
}

void inc_bcd()   {
char digit1 = 0;
char digit2 = 0;

digit1 = p_num & 0b00001111;
digit2 = p_num & 0b11110000;

if(digit1 == 9) {
    if(digit2 == 144) p_num = 0;              							//10010000 = 144
    else p_num=(p_num+7); 											
   }

else p_num++;
}

void dec_bcd()   {
char digit1 = 0;
char digit2 = 0;

digit1 = p_num & 0b00001111;
digit2 = p_num & 0b11110000;

if(digit1 == 0) {
   if(digit2==0) p_num = 0;
   else p_num=p_num-7;
   }

else p_num--;
}

char eeprom_valid_read(char loc)   {
   char store_1 = 0;
   char store_2 = 0;
   char store_3 = 0;
   char val = 0;

   disable_interrupts(global);  

   store_1 = read_eeprom(loc);
   store_2 = read_eeprom(loc+1);
   store_2 = read_eeprom(loc+2);

   if (store_1 == store_2) 				val = store_1;
   else if (store_2 == store_3) 		val = store_2 + 1;				//corruption occured when writing to 1st location
   else if   (store_1 == (store_3+1))	val = store_1;					//corruption occured when writing to 2nd location
   else val = 0;                              							//more than 1 value corrupted

   enable_interrupts(global);
   return val;
}

void eeprom_valid_write(char loc, char val)      {

	disable_interrupts(global);

	write_eeprom(loc,val);
	write_eeprom(loc+1,val);
	write_eeprom(loc+2,val);

	enable_interrupts(global);		
}

char get_resv_num()			{
	char current_num;

	current_num = ((p_num<<4)>>4) + (p_num>>4)*10; 

	if (num_array[num_index] != 0) num_index++;

	while	( (num_array[num_index] != 0) && (num_array[num_index] < (current_num+10)) ) num_index++;
	
	return num_array[num_index];
	
}